package com.github.anastr.speedviewlib;

import com.github.anastr.speedviewlib.components.Indicators.Indicator;
import com.github.anastr.speedviewlib.components.Indicators.NormalSmallIndicator;
import com.github.anastr.speedviewlib.components.Indicators.TriangleIndicator;
import com.github.anastr.speedviewlib.util.AttrSetUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

/**
 * this Library build By Anas Altair
 * see it on <a href="https://github.com/anastr/SpeedView">GitHub</a>
 */
public class DeluxeSpeedView extends Speedometer {

    private Path markPath = new Path(),
            smallMarkPath = new Path();
    private Paint circlePaint = new Paint(),
            speedometerPaint = new Paint(),
            markPaint = new Paint(),
            smallMarkPaint = new Paint(),
            speedBackgroundPaint = new Paint();
    private RectFloat speedometerRect = new RectFloat();

    private boolean withEffects = true;

    public DeluxeSpeedView(Context context) {
        this(context, null);
    }

    public DeluxeSpeedView(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public DeluxeSpeedView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);

        circlePaint.setAntiAlias(true);
        speedometerPaint.setAntiAlias(true);
        markPaint.setAntiAlias(true);
        smallMarkPaint.setAntiAlias(true);
        speedBackgroundPaint.setAntiAlias(true);
        init();
        initAttributeSet(context, attrSet);
    }

    @Override
    protected void defaultGaugeValues() {
        super.setTextColor(0xFFFFFFFF);
    }

    @Override
    protected void defaultSpeedometerValues() {
        super.setIndicator(new NormalSmallIndicator(getContext())
                .setIndicatorColor(0xff00ffec));
        super.setBackgroundCircleColor(0xff212121);
        super.setLowSpeedColor(0xff37872f);
        super.setMediumSpeedColor(0xffa38234);
        super.setHighSpeedColor(0xff9b2020);
    }


    private void init() {
        speedometerPaint.setStyle(Paint.Style.STROKE_STYLE);
        markPaint.setStyle(Paint.Style.STROKE_STYLE);
        smallMarkPaint.setStyle(Paint.Style.STROKE_STYLE);
        speedBackgroundPaint.setColor(new Color(0xFFFFFFFF));
        circlePaint.setColor(new Color(0xffe0e0e0));

        setWithEffects(withEffects);
    }

    private void initAttributeSet(Context context, AttrSet attrSet) {
        if (attrSet == null)
            return;

        speedBackgroundPaint.setColor(AttrSetUtils.getAttrSetColor(attrSet,"sv_speedBackgroundColor"
                , speedBackgroundPaint.getColor()));
        withEffects = AttrSetUtils.getBoolean(attrSet,"sv_withEffects", withEffects);
        circlePaint.setColor(AttrSetUtils.getAttrSetColor(attrSet,"sv_centerCircleColor", circlePaint.getColor()));

        setWithEffects(withEffects);
        initAttributeValue();
    }

    private void initAttributeValue() {
    }


    @Override
    protected void onSizeChange(int w, int h, int oldW, int oldH) {
        super.onSizeChange(w, h, oldW, oldH);
        updateBackgroundBitmap();
    }

    private void initDraw() {
        speedometerPaint.setStrokeWidth(getSpeedometerWidth());
        markPaint.setColor(new Color(getMarkColor()));
        smallMarkPaint.setColor(new Color(getMarkColor()));
    }

    @Override
    public void onDrawComponent(Component component, Canvas canvas) {
        super.onDrawComponent(component, canvas);

        RectFloat speedBackgroundRect = getSpeedUnitTextBounds();
        speedBackgroundRect.left -= 2;
        speedBackgroundRect.right += 2;
        speedBackgroundRect.bottom += 2;
        canvas.drawRect(speedBackgroundRect, speedBackgroundPaint);

        drawSpeedUnitText(canvas);
        drawIndicator(canvas);
        canvas.drawCircle(getSize() *.5f, getSize() *.5f, getWidthPa()/12f, circlePaint);
        drawNotes(canvas);
    }

    @Override
    protected void updateBackgroundBitmap() {
        Canvas c = createBackgroundBitmapCanvas();
        initDraw();

        float smallMarkH = getViewSizePa()/20f;
        smallMarkPath.reset();
        smallMarkPath.moveTo(getSize() *.5f, getSpeedometerWidth() + getCustomPadding());
        smallMarkPath.lineTo(getSize() *.5f, getSpeedometerWidth() + getCustomPadding() + smallMarkH);
        smallMarkPaint.setStrokeWidth(3);

        float markH = getViewSizePa()/28f;
        markPath.reset();
        markPath.moveTo(getSize() *.5f, getCustomPadding());
        markPath.lineTo(getSize() *.5f, markH + getCustomPadding());
        markPaint.setStrokeWidth(markH/3f);

        float risk = getSpeedometerWidth() *.5f + getCustomPadding();
        speedometerRect = new RectFloat(risk, risk, getSize() -risk, getSize() -risk);

        speedometerPaint.setColor(new Color(getHighSpeedColor()));
        c.drawArc(speedometerRect, new Arc(getStartDegree(), getEndDegree()- getStartDegree(), false), speedometerPaint);
        speedometerPaint.setColor(new Color(getMediumSpeedColor()));
        c.drawArc(speedometerRect,new Arc( getStartDegree()
                , (getEndDegree()- getStartDegree())*getMediumSpeedOffset(), false), speedometerPaint);
        speedometerPaint.setColor(new Color(getLowSpeedColor()));
        c.drawArc(speedometerRect, new Arc(getStartDegree()
                , (getEndDegree()- getStartDegree())*getLowSpeedOffset(), false), speedometerPaint);

        c.save();
        c.rotate(90f + getStartDegree(), getSize() *.5f, getSize() *.5f);
        float everyDegree = (getEndDegree() - getStartDegree()) * .111f;
        for (float i = getStartDegree(); i < getEndDegree()-(2f*everyDegree); i+=everyDegree) {
            c.rotate(everyDegree, getSize() *.5f, getSize() *.5f);
            c.drawPath(markPath, markPaint);
        }
        c.restore();

        c.save();
        c.rotate(90f + getStartDegree(), getSize() *.5f, getSize() *.5f);
        for (float i = getStartDegree(); i < getEndDegree() - 10f; i+=10f) {
            c.rotate(10f, getSize() *.5f, getSize() *.5f);
            c.drawPath(smallMarkPath, smallMarkPaint);
        }
        c.restore();

        if (getTickNumber() > 0)
            drawTicks(c);
        else
            drawDefMinMaxSpeedPosition(c);
    }


    public boolean isWithEffects() {
        return withEffects;
    }

    public void setWithEffects(boolean withEffects) {
        this.withEffects = withEffects;
        indicatorEffects(withEffects);
        if (withEffects) {
            markPaint.setMaskFilter(new MaskFilter(5, MaskFilter.Blur.SOLID));
            speedBackgroundPaint.setMaskFilter(new MaskFilter(8, MaskFilter.Blur.SOLID));
            circlePaint.setMaskFilter(new MaskFilter(10, MaskFilter.Blur.SOLID));
        }
        else {
            markPaint.setMaskFilter(null);
            speedBackgroundPaint.setMaskFilter(null);
            circlePaint.setMaskFilter(null);
        }
        updateBackgroundBitmap();
        invalidate();
    }

    @Override
    public void setIndicator(Indicator indicator) {
        super.setIndicator(indicator);
        indicatorEffects(withEffects);
    }

    public int getSpeedBackgroundColor() {
        return speedBackgroundPaint.getColor().getValue();
    }

    public void setSpeedBackgroundColor(int speedBackgroundColor) {
        speedBackgroundPaint.setColor(new Color(speedBackgroundColor));
        updateBackgroundBitmap();
        invalidate();
    }

    public int getCenterCircleColor() {
        return circlePaint.getColor().getValue();
    }

    /**
     * change the color of the center circle (if exist),
     * <b>this option is not available for all Speedometers</b>.
     * @param centerCircleColor new color.
     */
    public void setCenterCircleColor(int centerCircleColor) {
        circlePaint.setColor(new Color(centerCircleColor));
        if (!isAttachedToWindow())
            return;
        invalidate();
    }
}
